"""
高级平仓策略
支持多种出场条件：止盈、止损、时间超时等
"""
import pandas as pd
import numpy as np
from typing import Optional, Tuple
from src.utils.logger import get_logger

logger = get_logger(__name__)


class ExitStrategy:
    """高级出场策略 - 已简化版本"""

    def __init__(self, config: dict = None):
        """初始化出场策略"""
        self.config = config or {}

    def should_exit(self, position, current_bar: pd.Series, kline_data: dict,
                   bars_held: int, params: dict = None) -> Tuple[bool, str]:
        """
        判断是否应该平仓

        简化策略：
        - 移除过于激进的条件（momentum reversal, break-even exit）
        - 只保留最有效的出场条件
        - 优先级：硬超时 > 固定TP/SL > 软超时

        Args:
            position: 持仓对象
            current_bar: 当前K线
            kline_data: 多时间框架K线数据 (5分钟为主)
            bars_held: 持仓K线数
            params: 策略参数

        Returns:
            (是否平仓, 平仓原因)
        """
        if position is None:
            return False, "no_position"

        # 简化的出场条件 - 只保留有效的核心条件
        exit_checks = [
            self._check_hard_timeout,      # 硬超时 (20K线) - 风险限制
            self._check_fixed_tp_sl,        # 固定TP/SL - 核心出场
            self._check_soft_timeout,       # 软超时 - 后期调整
        ]

        for check_func in exit_checks:
            should_exit, reason = check_func(position, current_bar, kline_data, bars_held, params)
            if should_exit:
                logger.debug(f"平仓条件触发: {reason} (持仓{bars_held}根K线)")
                return True, reason

        return False, "holding"

    def _check_hard_timeout(self, position, current_bar: pd.Series, kline_data: dict,
                           bars_held: int, params: dict = None) -> Tuple[bool, str]:
        """硬超时: 必须在20K线内平仓"""
        max_bars = params.get('max_position_bars', 20) if params else 20
        if bars_held >= max_bars:
            return True, f"hard_timeout_{bars_held}bars"
        return False, ""

    def _check_fixed_tp_sl(self, position, current_bar: pd.Series, kline_data: dict,
                          bars_held: int, params: dict = None) -> Tuple[bool, str]:
        """
        固定TP/SL: 传统的固定百分比止盈止损

        这是最核心的出场条件，应该在大部分情况下触发
        """
        current_price = current_bar['close']
        pnl_pct = self._calculate_pnl_pct(position.side, position.entry_price, current_price)

        # 从参数中读取TP/SL，默认值为2%/1%
        tp = params.get('take_profit', 2.0) / 100 if params else 0.02
        sl = params.get('stop_loss', 1.0) / 100 if params else 0.01

        if pnl_pct >= tp * 100:
            return True, f"fixed_tp_{pnl_pct:.2f}%"
        elif pnl_pct <= -sl * 100:
            return True, f"fixed_sl_{pnl_pct:.2f}%"

        return False, ""

    def _check_soft_timeout(self, position, current_bar: pd.Series, kline_data: dict,
                           bars_held: int, params: dict = None) -> Tuple[bool, str]:
        """
        软超时: 在10K线后，使用更宽松的TP/SL

        目的是避免在8-9根K线时被强制平仓，给予更多机会等待反转
        """
        soft_timeout_bars = 10
        if bars_held < soft_timeout_bars:
            return False, ""

        current_price = current_bar['close']
        pnl_pct = self._calculate_pnl_pct(position.side, position.entry_price, current_price)

        # 在软超时区间内，降低TP要求但也提高SL宽松度
        soft_tp = params.get('take_profit', 2.0) * 0.5 / 100 if params else 0.01  # 降低到50%
        soft_sl = params.get('stop_loss', 1.0) * 2.0 / 100 if params else 0.02  # 加宽到200%

        if pnl_pct >= soft_tp * 100:
            return True, f"soft_timeout_tp_{pnl_pct:.2f}%"
        elif pnl_pct <= -soft_sl * 100:
            return True, f"soft_timeout_sl_{pnl_pct:.2f}%"

        return False, ""

    @staticmethod
    def _calculate_pnl_pct(side: str, entry_price: float, current_price: float) -> float:
        """计算盈亏百分比"""
        if side == "long":
            return ((current_price - entry_price) / entry_price) * 100
        else:
            return ((entry_price - current_price) / entry_price) * 100

